<template lang='pug'>
  .main-map
    section.map-tools(v-if="isEditing && noRelease")
      button.btn(
        :class="mouseTool ? 'btn-success' : 'btn-complete'"
        value="鼠标绘制面" id="polygon" @click="drawPolygon") {{mouseTool ? '退出绘制' : '绘制区域'}}
    SmartDialog.map-marker-dialog(v-model="showModalMarker" :title='dialogName' size="md")
      SmartForm.m-lg-3(
        v-model="markerValues"
        :formList="markerFormList"
        :columns="markerColns"
        :values="markerValues"
        :buttonList="markerButtons")
    el-amap(
      ref="map"
      vid="amap"
      v-loading="loading"
      element-loading-text="拼命加载中..."
      element-loading-spinner="el-icon-loading"
      element-loading-background="rgba(253, 253, 253, 0.9)"
      :amap-manager="amapManager"
      :center="center"
      :zoom="zoom"
      :events="events"
      :plugin="plugin")
      el-amap-marker(
        v-for="(item, index) in markers"
        :key="`marker_${index}`"
        :vid="`marker_${index}`"
        :position="item.position"
        :icon="item.icon"
        :events="item.events")
      //- el-amap-info-window.window-info(
      //-   v-if="isShowMessage && windowsPage.position"
      //-   ref="windowsPage"
      //-   :isCustom="true"
      //-   :position="windowsPage.position"
      //-   :content="windowsPage.content"
      //-   :offset="windowsPage.offset"
      //-   :events="windowsPage.events"
      //-   :visible="true"
      //-   :showShadow="true"
      //-   :closeWhenClickMap="true"
      //-   :autoMove="true")
      el-amap-info-window.window-info(
        v-if="isShowMessage && windowsPage.position"
        ref="windowsPage"
        :offset="windowsPage.offset"
        :showShadow="false"
        :position="windowsPage.position")
        InfoWindow(
          :columns="markerColns"
          :infoValues="windowsPage.data")
      el-amap-polygon(v-for="(polygon, index) in polygons"
        v-bind="polygon"
        :vid="`polygon_${index}`"
        :key="`polygon_${index}`"
        :ref="`polygon_${index}`"
        :path="polygon.path"
        :fillColor="polygon.fillColor"
        :editable="isEditing && editing === polygon.id && noRelease"
        :fillOpacity="polygon.fillOpacity"
        :strokeColor="polygon.strokeColor"
        :draggable="polygon.draggable"
        title="右键保存区域")
      el-amap-polygon(
        v-if="isClipPolygons"
        ref="clipPolygon"
        :path="isClipPolygons.path"
        :fillColor="isClipPolygons.fillColor"
        :editable="isEditing && canEditClip"
        :fillOpacity="isClipPolygons.fillOpacity"
        :strokeColor="isClipPolygons.strokeColor"
        :events="isClipPolygons.events")
      //- 编辑时文字提醒
      el-amap-text(
        v-if="opearTip.position && isEditing"
        :text="opearTip.title"
        :draggable="true"
        :editable="opearTip"
        :position="opearTip.position")
</template>

<script>
/**
 * @name 分区管理-地图控制
 * @author linmn
 */
// import VueAMap from 'vue-amap'
import {AMapManager} from 'vue-amap'
import {isArray, cloneDeep} from 'lodash' // debounce,
import {getDyncRelation} from '../lib/index'
import { infoRender } from '@/components/InfoRender/infoRender'
import SmartDialog from '@/components/SmartDialog/index'
import SmartForm from '@/components/SmartForm'
import InfoWindow from './InfoWindow'

import config from '@/pages/dpa/config'
import mapConfig from '@/pages/dpa/config/mapField'
import isOff from '../../assets/img/isOff.png'
import isOn from '../../assets/img/isOn.png'
// import InfoRender from '@/components/InfoRender/infoRender'
// import { cloneDeep } from 'lodash'
let amapManager = new AMapManager()
export default {
  name: 'MapPage',
  components: {
    SmartDialog,
    SmartForm,
    InfoWindow,
    isOff,
    isOn
  },
  props: {
    isEditing: {
      type: Boolean,
      default: false
    }, // 是否编辑地图
    mapDatas: {
      type: Array,
      default: () => ([])
    }, // 地图数据
    mapMarkers: {
      type: Array,
      default: () => ([])
    },
    version: {
      type: Object,
      default: () => ({})
    }
  },
  computed: {
    noRelease () {
      return this.version.status !== 'RELEASE' && !this.version.enabled
    },
    /* 地图色块区域 */
    polygons () {
      this.mapDatas.map((data, index) => {
        data.fillOpacity = this.clickPolygonIndex === index ? 0.8 : data.fillOpacity ? data.fillOpacity : 0.4
        data.events = this.InitPolygonsEvnts(data, index)
      })
      return this.mapDatas
    },
    newMap () {
      return amapManager.getMap()
    },
    markers () {
      return this.mapMarkers.map(data => {
        if (!data.longitude || !data.latitude) return data
        const lnglat = isArray(data) ? data : [data.longitude, data.latitude]
        const alls = {
          ...data.device,
          ...data
        }
        return {
          ...alls,
          position: lnglat,
          icon: data.enabledBoundary ? isOn : isOff,
          events: {
            mouseover: () => this.renderWinInfo(alls, lnglat, mapConfig.mapList),
            mouseout: () => this.closeWindowInfo(),
            click: () => this.handleClickMarker(alls)
          },
          clickable: true,
          draggable: false
        }
      })
    }
  },
  watch: {
    mapDatas (datas = []) {
      this.renderText(datas)
      // this.clearAllClick()
    },
    isEditing (data) {
      if (!data) this.clearMouseTool()
    }
  },
  created () {
    const {columns} = getDyncRelation({target: this, columns: mapConfig.mapColumns})
    this.markerColns = columns
  },
  destroyed () {
    // console.info('isDestory--')
    this.clearMouseTool()
  },
  data () {
    return {
      mapConfig: mapConfig,
      loading: false,
      center: config.KLMY.lonlat,
      zoom: 11,
      editing: null, // 编辑中色块的id
      amapManager,
      isShowMessage: false,
      showModalMarker: false,
      canEditClip: true,
      windowsPage: {},
      isClipPolygons: null,
      opearTip: {}, // 操作提醒
      CtextMenu: {}, // 菜单对象
      events: {
        init: (o) => {
          this.renderText(this.mapDatas)
          // this.CtextMenu = new AMap.ContextMenu()
          // this.CtextMenu.addItem('保存区域', () => {})
          // this.CtextMenu.addItem('删除区域')
        },
        click: (e) => this.clearAllClick()
      },
      plugin: [{
        pName: 'ToolBar',
        liteStyle: true,
        position: 'RB'
      }],
      /* 坐标 */
      // mapMarkers: [],
      text: [],
      /* 鼠标绘图工具 */
      mouseTool: null,
      /* 坐标点表单参数 */
      dialogName: '',
      markerFormList: mapConfig.markerList,
      markerColns: {},
      markerValues: {},
      markerButtons: [{
        label: '保存',
        icon: 'save',
        type: 'complete',
        validate: true,
        func: ({funcProps}) => {
          const {form} = funcProps
          const {formValues} = form
          this.$emit('postDevice', formValues)
        }
      }],
      clickPolygonIndex: null
    }
  },
  methods: {
    /* 多边形默认事件 */
    InitPolygonsEvnts (data, index) {
      let adjustPaths = null
      return {
        click: (datas) => this.clickPolygon(data, index),
        adjust: (datas) => {
          const newPaths = this.$refs[`polygon_${index}`][0].path
          this.adjustPolygon(newPaths, datas.lnglat, (range) => {
            adjustPaths = range
          })
        },
        dblclick: () => {
          // 双击保存修改区域(无修改状态下双击取消修改)
          if (!adjustPaths) return
          this.judgeMultiPolygon(adjustPaths, data.id, () => {
            this.$emit('adjustPolygon', adjustPaths, data)
          }, () => {
            this.drawEditablePolygon(adjustPaths, data)
          })
        }
        // rightclick: (e) => {
        //   console.log('is Right::')
        //   if (!this.isEditing) return
        //   this.CtextMenu.open(this.newMap, [e.lnglat.lng, e.lnglat.lat])
        // }
        // mouseover: (e) => {
        //   const lnglat = [e.lnglat.lng, e.lnglat.lat]
        //   this.renderWinInfo(data, lnglat, ['name'])
        // },
        // mouseout: () => this.closeWindowInfo()
      }
    },
    /* 绘画多边形 */
    drawPolygon () {
      this.editing = null
      if (this.mouseTool) {
        this.clearMouseTool()
        return
      }
      // console.log('this.mouseTool::', this.mouseTool)
      this.reopenMouseTool() // 重启画笔
      this.mouseTool.polygon()
      this.mouseTool.on('draw', ({obj}) => {
        const newLngLat = obj.getPath().map(cell => {
          return [cell.lng, cell.lat]
        })
        this.judgeMultiPolygon(obj.getPath(), null, () => {
          this.$emit('createPolygon', newLngLat)
          this.clearMouseTool()
        }, () => {
          this.drawEditablePolygon(obj.getPath())
        })
      })
    },
    /* 创建新区域允许用户重新编辑，直到没有重叠，才允许创建 */
    drawEditablePolygon (range, target = null) {
      this.$swalPrompt({
        title: '错误',
        text: '绘制的区域重叠，请重新调整',
        type: 'error',
        confirmButtonText: '调整一下',
        cancelButtonText: '丢弃绘制'
      }, () => {
        // 调整一下
        this.clearMouseTool()
        this.canEditClip = true
        let adjustPaths = []
        if (target) return
        // console.log('just-create')
        this.isClipPolygons = {
          path: range, // 设置线覆盖物路径
          strokeColor: '#539DFB', // 线颜色
          strokeOpacity: 1, // 线透明度
          strokeWeight: 5, // 线宽
          strokeStyle: 'dashed', // 线样式
          strokeDasharray: [10, 5], // 补充线样式
          fillColor: '#B6D3F4',
          fillOpacity: 0.4,
          events: {
            rightClick: (e) => {
              // TODO 右键删除
            },
            adjust: (datas) => {
              const newPaths = this.$refs.clipPolygon.path
              this.adjustPolygon(newPaths, datas.lnglat, (range) => {
                // console.log('is adjust')
                adjustPaths = range
              })
            },
            dblclick: () => {
              // 双击保存新建区域(无调整修改状态下双击拿原先画的路径对比)
              adjustPaths = adjustPaths.length ? adjustPaths : this.isClipPolygons.path
              this.judgeMultiPolygon(adjustPaths, null, () => {
                this.canEditClip = false
                this.opearTip = {}
                this.$emit('createPolygon', adjustPaths)
                setTimeout(() => {
                  this.isClipPolygons = null
                }, 100)
              }, () => {
                this.drawEditablePolygon(adjustPaths)
              })
            }
          }
        }
      }, () => {
        // 取消保存
        this.isClipPolygons = null
        this.clearMouseTool()
        this.opearTip = {}
        setTimeout(() => {
          // 取消绘制后允许重新绘制
          this.drawPolygon()
        }, 100)
      })
    },
    /* 处理重叠区域 */
    judgeMultiPolygon (paths = [], id, resolve = () => {}, reject = () => {}) {
      const {hasClip} = this.computeRingRingClip(paths, id)
      console.log('hasClip:', hasClip)
      if (hasClip) {
        // 拒绝
        this.opearTip = {
          position: isArray(paths[0]) ? paths[0] : [paths[0].lng, paths[0].lat],
          title: '双击区域保存修改'
        }
        reject()
      } else {
        // 允许
        this.opearTip = {}
        resolve()
      }
    },
    /* 清除绘制工具 */
    clearMouseTool () {
      if (!this.mouseTool) return
      this.mouseTool.close(true)
      this.mouseTool = null
      this.canEditClip = false
    },
    /* 重启绘制工具 */
    reopenMouseTool () {
      this.mouseTool = new AMap.MouseTool(this.newMap)
      // this.mouseTool.close(false)
    },
    // 渲染多边形中心点的文字
    renderText (lnglat, paths = this.mapDatas) {
      // if (!this.mapDatas || !this.mapDatas.length) return
      this.text.map(item => {
        item.setMap(null)
      })
      this.text = paths.map(data => {
        // 同个中心点聚合 TODO
        const center = data.areaCenter[0] || data.areaCenter[1] ? data.areaCenter : data.path[0]
        return new AMap.Text({
          text: data.name,
          // position: data.path[0],
          position: center,
          map: this.newMap,
          style: {
            'background-color': data.color,
            'color': '#ffffff',
            'font-size': '14px',
            'padding': '3px 20px',
            'border-color': '#e4e7ed'
          }
        })
        // this.text.setMap(o)
      })
    },
    /* 坐标点事件 */
    closeWindowInfo () {
      this.isShowMessage = false
    },
    /* 编辑设备 */
    handleClickMarker (datas) {
      if (!this.version.enabled || !this.isEditing) return
      this.showModalMarker = true
      this.markerValues = datas
      this.$set(this, 'markerValues', datas)
      this.dialogName = `坐标点【${datas.deviceType}】信息编辑`
      // this.$emit('MarkerEdit')
    },
    /* 渲染窗体信息 */
    renderWinInfo (datas, lnglat, list) {
      // console.log('lnglat0', lnglat)
      this.isShowMessage = true
      this.windowsPage = {
        position: lnglat,
        data: datas,
        list: list,
        offset: [-15, -45]
      }
    },
    showInfoData (val, list) {
      const columns = this.markerColns
      // const {columns} = getDyncRelation({target: this, columns: mapConfig.mapColumns})
      let data = ''
      list.map((info, key) => {
        const infoValue = infoRender({
          data: val[info],
          column: columns[info],
          full: val,
          index: key
        })
        data += `<p style="margin: 0"><span class="info-label">${columns[info].label}</span>：${infoValue}</p>`
      })
      return data
    },
    /* 多边形触动 */
    clickPolygon (data, index) {
      this.editing = data.id
      if (this.clickPolygonIndex !== null && this.mapDatas[this.clickPolygonIndex] && index !== this.clickPolygonIndex) {
        this.$set(this.mapDatas[this.clickPolygonIndex], 'fillOpacity', 0.4)
      }
      this.clickPolygonIndex = index
      this.$emit('selectPolygon', data.id)
    },
    /* 清除地图上点击 */
    clearAllClick () {
      console.log('clearAllClick')
      this.clickPolygonIndex = null
      this.$emit('selectPolygon', null)
    },
    /**
     * @desc 允许拖动修改范围
     * @TODO 判断范围
     * */
    adjustPolygon (nPaths, {lng, lat}, cb = () => {}) {
      // 形成新的色块
      const temp = nPaths.map(path => {
        return [path.lng, path.lat]
      })
      // this.opearTip = {
      //   position: temp[0],
      //   title: '双击保存修改'
      // }
      cb(temp)
    },
    polygonReRender (target, val) {
      target.fillOpacity = val
    },
    /**
     * 判断是否
    */
    /**
     * @desc 计算重叠区域
     * @params {Array} tPath 目标范围
     * @return {Array} 去除重合区域的范围
     * @return {Boolean} 是否有点重合
    */
    computeRingRingClip (tPath = [], id = null) {
      let newPath = cloneDeep(tPath)
      let clipPoints = []
      let isRing = false
      const targetDatas = this.mapDatas.filter(data => data.id !== id)
      targetDatas.map(({path}) => {
        isRing = AMap.GeometryUtil.doesRingRingIntersect(tPath, path)
        if (isRing) {
          newPath.map((point, index) => {
            const ringInRing = AMap.GeometryUtil.isPointInRing(point, path)
            if (ringInRing) {
              clipPoints.push(newPath)
              this.$delete(newPath, index)
            }
          })
          // const overRings = AMap.GeometryUtil.ringRingClip(tPath, path) // 计算重叠区域 - 无效
        }
      })
      // this.clearMouseTool()
      return {
        range: tPath, // 目前只能判断点在区域内
        hasClip: clipPoints.length || isRing
      }
    },
    computePointInRing (lnglat) {
      const inRing = this.mapDatas.filter(({path}) => AMap.GeometryUtil.isPointInRing(lnglat, path))
      return inRing
    }
  }
}
</script>

<style lang='sass' scoped>
.main-map
  position: relative
  height: 100%
  .map-tools
    position: absolute
    bottom: 20px
    left: 148px
    z-index: 9
    padding: 10px 20px
.hidden
  visibility: hidden
.info-label
  min-width: 100px
  display: inline-block
  text-align: right
  margin-right: 15px
</style>
